﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WCS.Controls.RunLog;
using WCS.Entity;
using WCS.Utils;

namespace Service
{
    public class ServiceSocker
    {
        private ServiceSocker() { }

        private static readonly ServiceSocker serviceSocker = new ServiceSocker();

        public static ServiceSocker _serviceSocker
        {
            get
            {
                return serviceSocker;
            }
        }

        public delegate bool ClientComplete(string TaskCode);

        public static event ClientComplete clienTasktComplete;

        /// <summary>
        /// 数据库连接对象
        /// </summary>
        static SqlSugarDapper _SqlSugarDapper = SqlSugarDapper.GetDbContext();

        /// <summary>
        /// 客户端心跳超时时间
        /// </summary>
        int TimeOut = Convert.ToInt32(ConfigurationManager.AppSettings["TimeOut"]);

        /// <summary>
        /// 是否继续监听
        /// </summary>
        bool _isListening = false;//监听

        /// <summary>
        /// 服务器对象
        /// </summary>
        Socket socketStart;

        /// <summary>
        /// 客户端对象集合
        /// </summary>
        public List<ClientSocketConnect> clientSocketConnects = new List<ClientSocketConnect>();

        /// <summary>
        /// 服务器端口
        /// </summary>
        int port = Convert.ToInt32(ConfigurationManager.AppSettings["WcsServicePort"]);

        /// <summary>
        /// 服务器IP
        /// </summary>
        IPAddress ip = IPAddress.Any;  // 侦听所有网络客户接口的客活动

        /// <summary>
        /// 交互步骤集合
        /// </summary>
        public List<WCSInteractiveStep> WCSInteractiveStepList;

        /// <summary>
        /// 创建服务器
        /// </summary>
        public void CreateService()
        {

            socketStart = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//使用指定的地址簇协议、套接字类型和通信协议   <br>            ReceiveSocket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReuseAddress,true);  //有关套接字设置
            socketStart.Bind(new IPEndPoint(IPAddress.Parse("192.168.1.2"), port)); //绑定IP地址和端口号
            socketStart.Listen(10);  //设定最多有10个排队连接请求

            //初始化数据
            WCSInteractiveStepList = _SqlSugarDapper.DB.Queryable<WCSInteractiveStep>().ToList();

            //启用监听
            Task.Run(() => AcceptWork());

            //心跳检测
            //Task.Run(() => Heartbeat());
        }

        /// <summary>
        /// 服务器监听
        /// </summary>
        public void AcceptWork()
        {
            try
            {
                while (!_isListening)
                {
                    Socket socket = socketStart.Accept();

                    Task.Run(() => ReceiveMessage(socket));

                    var cli = new ClientSocketConnect { Name = "灯光控制器", Client = socket, LastHeartDate = DateTime.Now };
                    clientSocketConnects.Add(cli);
                    Thread.Sleep(200);
                }
            }
            catch (Exception ex)
            {
                RunLog.runLog.Error($@"异常信息【{ex.Message}】【{ex.StackTrace}】");
            }
        }

        /// <summary>
        /// 返回消息
        /// </summary>
        private void ReceiveMessage(Socket socket)
        {
            try
            {
                while (true)
                {
                    byte[] receive = new byte[2000];
                    var asdsa = socket.Receive(receive);

                    if (true)
                    {
                        //处理接受数据
                        //ReceiveMessageProcessing(socket, receive);
                    }
                    else
                    {
                        var t = receive.Take(4).ToArray();
                        var w = receive.Skip(receive.Length - 4).ToArray();

                        int add = ByteToInt(t);
                        var ad = w[0].ToString();
                        var s = Encoding.UTF8.GetString(w);

                        var asda = Encoding.UTF8.GetString(receive.Take(receive.Length - 4).Skip(4).ToArray());
                        var name = JsonConvert.DeserializeObject<Data>(asda);
                        var d = clienTasktComplete.Invoke(name.TaskCode);
                        //var d = clienTasktComplete(name.TaskCode);
                    }

                    //byte[] send = Encoding.UTF8.GetBytes($"返回给客户端【{socket.RemoteEndPoint}】");
                    //socket.Send(send);
                    //RunLog.runLog.Debug($"发送消息为：" + Encoding.UTF8.GetString(send));

                    Thread.Sleep(200);
                }
            }
            catch (Exception ex)
            {
                RunLog.runLog.Error($@"异常信息【{ex.Message}】【{ex.StackTrace}】");
            }
        }

        /// <summary>  
        /// 字节byte 转int        
        /// </summary>        
        /// <param name="data"></param>        
        /// <returns></returns>        
        public int ByteToInt(byte[] data)
        {
            if (BitConverter.IsLittleEndian)
                Array.Reverse(data);
            int ilen = BitConverter.ToUInt16(data, 0);
            return ilen;
        }

        /// <summary>
        /// 接受消息类型
        /// </summary>
        /// <param name="ReceiveData"></param>
        private void ReceiveMessageProcessing(Socket socket, byte[] ReceiveData)
        {
            try
            {
                var asda = Encoding.Default.GetString(ReceiveData);
                var ReveiveMessage = JsonConvert.DeserializeObject<Data>(Encoding.UTF8.GetString(ReceiveData));
                //如果是连接包
                if (ReveiveMessage.PackageType == "Connect")
                {
                    var cli = new ClientSocketConnect { Name = ReveiveMessage.Name, Client = socket, LastHeartDate = DateTime.Now };

                    RunLog.runLog.Debug($"接收到【{socket.RemoteEndPoint}】消息：" + JsonConvert.DeserializeObject(asda));

                    var clientSocket = clientSocketConnects.Find(c => c.Name == cli.Name);

                    //当前客户端对象是否存在连接集合中
                    if (clientSocket == null)
                    {
                        //加入集合
                        clientSocketConnects.Add(cli);
                        if (clientSocketConnects.Count == 9)
                        {
                            //停止监听
                            _isListening = true;
                        }
                        RunLog.runLog.Debug($"【{socket.RemoteEndPoint}】建立连接");
                    }
                    else
                    {
                        //name相等 更新最后心跳时间
                        clientSocket.LastHeartDate = DateTime.Now;
                    }
                }
                else if (ReveiveMessage.PackageType == "Task")//任务包
                {
                    var task = _SqlSugarDapper.DB.Queryable<WcsTaskAGV>().Where(w => w.Task_Code == ReveiveMessage.TaskCode).ToList().First();
                    var step = WCSInteractiveStepList.Find(w => w.CurrentState == task.Task_State && ReveiveMessage.SendState == w.SendState &&
                    ReveiveMessage.InteractiveDev == w.InteractiveDev && "Send" != w.InteractiveType);

                    if (step != null)
                    {
                        _SqlSugarDapper.DB.Updateable<WcsTaskAGV>()
                            .SetColumns(w => w.Task_State == Convert.ToInt32(step.TargetState))
                            .Where(w => w.Task_Code == ReveiveMessage.TaskCode)
                            .ExecuteCommand();
                        RunLog.runLog.Debug($"【{step.InteractiveDev}】------【WCS】接受消息为:【{step.Remarks}】更新步骤为【{task.Task_State}】 ===> 【{step.TargetState}】");
                    }

                    //SendTask();
                }
            }
            catch (Exception ex)
            {
                RunLog.runLog.Error($@"异常信息【{ex.Message}】【{ex.StackTrace}】");
            }
        }

        /// <summary>
        /// 发送任务
        /// </summary>
        public void SendTask()
        {
            clientSocketConnects.Find(w => w.Name.Contains("灯光")).Client.Send(Encoding.ASCII.GetBytes($"AT+STACH3=1\r\n"));

            var task = _SqlSugarDapper.DB.Queryable<WcsTaskAGV>().ToList().First();
            var step = WCSInteractiveStepList.Find(w => w.CurrentState == task.Task_State && w.InteractiveType == "Send");
            if (step != null)
            {
                //创建要发送的数据
                var data = new Data { Name = "服务器", SendState = step.SendState, TaskCode = task.Task_Code };
                if (step.InteractiveDev == "AGV")
                {
                    //找到name对应的客户端
                    var client = clientSocketConnects.Find(c => c.Name == "AGV");
                    if (client != null)
                    {
                        //给客户端下发数据
                        client.Client.Send(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data)));
                    }

                    _SqlSugarDapper.DB.Updateable<WcsTaskAGV>()
                        .SetColumns(w => w.Task_State == Convert.ToInt32(step.TargetState))
                        .Where(w => w.Task_Code == task.Task_Code)
                        .ExecuteCommand();
                }
                else if (step.InteractiveDev == "PLC")
                {
                    clientSocketConnects.Find(c => c.Name == "PLC");

                    var client = clientSocketConnects.Find(c => c.Name == "PLC");
                    if (client != null)
                    {
                        client.Client.Send(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data)));
                    }
                    _SqlSugarDapper.DB.Updateable<WcsTaskAGV>()
                        .SetColumns(w => w.Task_State == Convert.ToInt32(step.TargetState))
                        .Where(w => w.Task_Code == task.Task_Code)
                        .ExecuteCommand();

                    RunLog.runLog.Debug($"【WCS】-----【{step.InteractiveDev}】发送消息为:【{step.Remarks}】更新步骤为【{task.Task_State}】 ===> 【{step.TargetState}】");

                }
            }
        }

        /// <summary>
        /// 心跳检测
        /// </summary>
        public void Heartbeat()
        {
            while (true)
            {
                foreach (var clientSocketConnect in clientSocketConnects.ToArray())
                {
                    //当前时间 减掉 最后心跳时间
                    var intervalDate = (DateTime.Now - clientSocketConnect.LastHeartDate).Seconds;

                    //秒数大于设定的时间
                    if (intervalDate > TimeOut)
                    {
                        //移除并关闭连接
                        clientSocketConnects.Remove(clientSocketConnect);
                        clientSocketConnect.Client.Close();
                        _isListening = false;

                        //继续监听
                        AcceptWork();
                        RunLog.runLog.Warning($"【{clientSocketConnect.Client.RemoteEndPoint}】心跳超时，主动断开");
                    }
                }
                Thread.Sleep(5000);
            }
        }

        public void ServiceSend()
        {
            var task = _SqlSugarDapper.DB.Queryable<WcsTaskAGV>().ToList().First();

            if (WCSInteractiveStepList != null)
            {
                var step = WCSInteractiveStepList.Find(w => w.CurrentState == task.Task_State && w.InteractiveType == "Send");
                if (step != null)
                {
                    //创建要发送的数据
                    var data = new Data { Name = "服务器", SendState = step.SendState, TaskCode = task.Task_Code };
                    //找到name对应的客户端
                    var client = ServiceSocker._serviceSocker.clientSocketConnects.Find(c => c.Name == step.InteractiveDev);
                    if (client != null)
                    {
                        //给客户端下发数据
                        client.Client.Send(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data)));

                        _SqlSugarDapper.DB.Updateable<WcsTaskAGV>()
                            .SetColumns(w => w.Task_State == Convert.ToInt32(step.TargetState))
                            .Where(w => w.Task_Code == task.Task_Code)
                            .ExecuteCommand();

                        RunLog.runLog.Debug($"【WCS】------【{step.InteractiveDev}】发送消息为:【{step.Remarks}】更新步骤为【{task.Task_State}】 ===> 【{step.TargetState}】");
                    }
                    else
                    {
                        RunLog.runLog.Debug($"【客户端{step.InteractiveDev}】未连接");
                    }
                }
            }
        }
    }

    public class ClientSocketConnect
    {
        public string Name { get; set; }

        public DateTime LastHeartDate { get; set; }

        public Socket Client { get; set; }
    }

    public class Data
    {
        /// <summary>
        /// 设备名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 包类型
        /// </summary>
        public string PackageType { get; set; }

        /// <summary>
        /// 发送状态
        /// </summary>
        public int SendState { get; set; }

        /// <summary>
        /// 交互设备
        /// </summary>
        public string InteractiveDev { get; set; }

        /// <summary>
        /// 任务号
        /// </summary>
        public string TaskCode { get; set; }
    }
}
